from dataclasses import dataclass, field
from typing import Literal

from .base import DOMConfig, Node


@dataclass(kw_only=True, slots=True, repr=False)
class HTMLElement(Node):
    """Base HTML Element.

    see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes
    """

    accesskey: str | None = None
    """The accesskey global attribute provides a hint for
    generating a keyboard shortcut for the current element.
    The attribute value must consist of a single printable
    character (which includes accented and other characters
    that can be generated by the keyboard)."""

    autocapitalize: Literal[
        "off", "none", "on", "sentences", "words", "characters"
    ] | None = None
    """The autocapitalize global attribute is an enumerated
    attribute that controls whether and how text input is
    automatically capitalized as it is entered/edited by the
    user."""

    autofocus: bool = False
    """The autofocus global attribute is a Boolean attribute
    indicating that an element should be focused on page load,
    or when the <dialog> that it is part of is displayed."""

    class_: str | None = None
    """The class global attribute is a space-separated list of the
    case-sensitive classes of the element. Classes allow CSS
    and JavaScript to select and access specific elements via
    the class selectors or functions like the DOM method
    document.getElementsByClassName."""

    contenteditable: Literal["true", "false", "plaintext-only"] | None = None
    """The contenteditable global attribute is an enumerated
    attribute indicating if the element should be editable by
    the user. If so, the browser modifies its widget to allow
    editing."""

    dir: Literal["ltr", "rtl", "auto"] | None = None
    """The dir global attribute is an enumerated attribute that
    indicates the directionality of the element's text."""

    draggable: Literal["true", "false"] | None = None
    """The draggable global attribute is an enumerated attribute
    that indicates whether the element can be dragged, either
    with native browser behavior or the HTML Drag and Drop API."""

    enterkeyhint: Literal[
        "enter", "done", "go", "next", "previous", "search", "send"
    ] | None = None
    """The enterkeyhint global attribute is an enumerated
    attribute defining what action label (or icon) to present
    for the enter key on virtual keyboards."""

    exportparts: str | None = None
    """The exportparts global attribute allows you to select and
    style elements existing in nested shadow trees, by
    exporting their part names."""

    hidden: bool = False
    """The hidden global attribute is an enumerated attribute
    indicating that the browser should not render the contents
    of the element. For example, it can be used to hide
    elements of the page that can't be used until the login
    process has been completed."""

    id: str | None = None
    """The id global attribute defines an identifier (ID) which
    must be unique in the whole document. Its purpose is to
    identify the element when linking (using a fragment
    identifier), scripting, or styling (with CSS)."""

    inert: bool = False
    """The inert global attribute is a Boolean attribute
    indicating that the browser will ignore the element. With
    the inert attribute, all of the element's flat tree
    descendants (such as modal <dialog>s) that don't otherwise
    escape inertness are ignored. The inert attribute also
    makes the browser ignore input events sent by the user,
    including focus-related events and events from assistive
    technologies."""

    inputmode: Literal[
        "none", "text", "decimal", "numeric", "tel", "search", "email", "url"
    ] | None = None
    """The inputmode global attribute is an enumerated attribute
    that hints at the type of data that might be entered by the
    user while editing the element or its contents. This allows
    a browser to display an appropriate virtual keyboard."""

    is_: str | None = None
    """The is global attribute allows you to specify that a
    standard HTML element should behave like a defined custom
    built-in element (see Using custom elements for more details)."""

    itemid: str | None = None
    """The itemid global attribute provides microdata in the form
    of a unique, global identifier of an item."""

    itemprop: str | None = None
    """The itemprop global attribute is used to add properties to
    an item. Every HTML element can have an itemprop attribute
    specified, and an itemprop consists of a name-value pair.
    Each name-value pair is called a property, and a group of
    one or more properties forms an item. Property values are
    either a string or a URL and can be associated with a very
    wide range of elements including <audio>, <embed>,
    <iframe>, <img>, <link>, <object>, <source>, <track>, and
    <video>."""

    itemref: str | None = None
    """Properties that are not descendants of an element with the
    itemscope attribute can be associated with an item using
    the global attribute itemref."""

    itemscope: str | None = None
    """itemscope is a boolean global attribute that defines the
    scope of associated metadata. Specifying the itemscope
    attribute for an element creates a new item, which results
    in a number of name-value pairs that are associated with
    the element."""

    itemtype: str | None = None
    """The global attribute itemtype specifies the URL of the
    vocabulary that will be used to define itemprop's (item
    properties) in the data structure."""

    lang: str | None = None
    """The lang global attribute helps define the language of an
    element: the language that non-editable elements are
    written in, or the language that the editable elements
    should be written in by the user. The attribute contains a
    single "language tag" in the format defined in RFC 5646:
    Tags for Identifying Languages (also known as BCP 47)."""

    nonce: str | None = None
    """The nonce global attribute is a content attribute defining
    a cryptographic nonce ("number used once") which can be
    used by Content Security Policy to determine whether or not
    a given fetch will be allowed to proceed for a given element."""

    part: str | None = None
    """The part global attribute contains a space-separated list
    of the part names of the element. Part names allows CSS to
    select and style specific elements in a shadow tree via the
    ::part pseudo-element."""

    popover: bool = False
    """The popover global attribute is used to designate an
    element as a popover element."""

    slot: str | None = None
    """The slot global attribute assigns a slot in a shadow DOM
    shadow tree to an element: An element with a slot attribute
    is assigned to the slot created by the <slot> element whose
    name attribute's value matches that slot attribute's value."""

    spellcheck: Literal["", "true", "false", "default"] | None = None
    """The spellcheck global attribute is an enumerated attribute
    that defines whether the element may be checked for
    spelling errors."""

    style: str | None = None
    """The style global attribute contains CSS styling
    declarations to be applied to the element. Note that it is
    recommended for styles to be defined in a separate file or
    files. This attribute and the <style> element have mainly
    the purpose of allowing for quick styling, for example for
    testing purposes."""

    tabindex: str | None = None
    """The tabindex global attribute allows developers to make
    HTML elements focusable, allow or prevent them from being
    sequentially focusable (usually with the Tab key, hence the
    name) and determine their relative ordering for sequential
    focus navigation."""

    title: str | None = None
    """The title global attribute contains text representing
    advisory information related to the element it belongs to."""

    translate: Literal["yes", "no"] | None = None
    """The translate global attribute is an enumerated attribute
    that is used to specify whether an element's translatable
    attribute values and its Text node children should be
    translated when the page is localized, or whether to leave
    them unchanged."""

    virtualkeyboardpolicy: Literal["auto", "manual"] | None = None
    """The virtualkeyboardpolicy global attribute is an enumerated
    attribute. When specified on an element that also uses the
    contenteditable attribute, it controls the on-screen
    virtual keyboard behavior on devices such as tablets,
    mobile phones, or other devices where a hardware keyboard
    may not be available."""

    data_attr: dict[str, str] = field(default_factory=dict)
    """The data-* global attributes form a class of attributes
    called custom data attributes, that allow proprietary
    information to be exchanged between the HTML and its DOM
    representation by scripts.
    Add without 'data-' infront"""

    # aria role
    role: str | None = None
    """aria role attribute: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles"""

    aria_attr: dict[str, str | bool] = field(default_factory=dict)
    """The aria-* global attributes.

    see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes

    Add without 'aria-' infront"""

    # event handler attributes
    onabort: str | None = None
    onautocomplete: str | None = None
    onautocompleteerror: str | None = None
    onblur: str | None = None
    oncancel: str | None = None
    oncanplay: str | None = None
    oncanplaythrough: str | None = None
    onchange: str | None = None
    onclick: str | None = None
    onclose: str | None = None
    oncontextmenu: str | None = None
    oncuechange: str | None = None
    ondblclick: str | None = None
    ondrag: str | None = None
    ondragend: str | None = None
    ondragenter: str | None = None
    ondragleave: str | None = None
    ondragover: str | None = None
    ondragstart: str | None = None
    ondrop: str | None = None
    ondurationchange: str | None = None
    onemptied: str | None = None
    onended: str | None = None
    onerror: str | None = None
    onfocus: str | None = None
    oninput: str | None = None
    oninvalid: str | None = None
    onkeydown: str | None = None
    onkeypress: str | None = None
    onkeyup: str | None = None
    onload: str | None = None
    onloadeddata: str | None = None
    onloadedmetadata: str | None = None
    onloadstart: str | None = None
    onmousedown: str | None = None
    onmouseenter: str | None = None
    onmouseleave: str | None = None
    onmousemove: str | None = None
    onmouseout: str | None = None
    onmouseover: str | None = None
    onmouseup: str | None = None
    onmousewheel: str | None = None
    onpause: str | None = None
    onplay: str | None = None
    onplaying: str | None = None
    onprogress: str | None = None
    onratechange: str | None = None
    onreset: str | None = None
    onresize: str | None = None
    onscroll: str | None = None
    onseeked: str | None = None
    onseeking: str | None = None
    onselect: str | None = None
    onshow: str | None = None
    onsort: str | None = None
    onstalled: str | None = None
    onsubmit: str | None = None
    onsuspend: str | None = None
    ontimeupdate: str | None = None
    ontoggle: str | None = None
    onvolumechange: str | None = None
    onwaiting: str | None = None

    # htmx attributes: https://htmx.org/reference/
    hx_boost: str | None = None
    """add or remove progressive enhancement for links and forms"""

    hx_get: str | None = None
    """issues a GET to the specified URL"""

    hx_post: str | None = None
    """issues a POST to the specified URL"""

    hx_on: str | None = None
    """handle any event with a script inline"""

    hx_push_url: str | None = None
    """pushes the URL into the browser location bar, creating a new history entry"""

    hx_select: str | None = None
    """select content to swap in from a response"""

    hx_select_oob: str | None = None
    """select content to swap in from a response, out of band (somewhere other
    than the target)"""

    hx_swap: str | None = None
    """controls how content is swapped in (outerHTML, beforeend, afterend, …)"""

    hx_swap_oob: str | None = None
    """marks content in a response to be out of band (should swap in somewhere other
    than the target)"""

    hx_target: str | None = None
    """specifies the target element to be swapped"""

    hx_trigger: str | None = None
    """specifies the event that triggers the request"""

    hx_vals: str | None = None
    """adds values to the parameters to submit with the request (JSON-formatted)"""

    hx_confirm: str | None = None
    """shows a confirm() dialog before issuing a request"""

    hx_delete: str | None = None
    """issues a DELETE to the specified URL"""

    hx_disable: str | None = None
    """disables htmx processing for the given node and any children nodes"""

    hx_disinherit: str | None = None
    """control and disable automatic attribute inheritance for child nodes"""

    hx_encoding: str | None = None
    """changes the request encoding type"""

    hx_ext: str | None = None
    """extensions to use for this element"""

    hx_headers: str | None = None
    """adds to the headers that will be submitted with the request"""

    hx_history: str | None = None
    """prevent sensitive data being saved to the history cache"""

    hx_history_elt: str | None = None
    """the element to snapshot and restore during history navigation"""

    hx_include: str | None = None
    """include additional data in requests"""

    hx_indicator: str | None = None
    """the element to put the htmx-request class on during the request"""

    hx_params: str | None = None
    """filters the parameters that will be submitted with a request"""

    hx_patch: str | None = None
    """issues a PATCH to the specified URL"""

    hx_preserve: str | None = None
    """specifies elements to keep unchanged between requests"""

    hx_prompt: str | None = None
    """shows a prompt() before submitting a request"""

    hx_put: str | None = None
    """issues a PUT to the specified URL"""

    hx_replace_url: str | None = None
    """replace the URL in the browser location bar"""

    hx_request: str | None = None
    """configures various aspects of the request"""

    hx_sse: str | None = None
    """has been moved to an extension. Documentation for older versions"""

    hx_sync: str | None = None
    """control how requests made by different elements are synchronized"""

    hx_validate: str | None = None
    """force elements to validate themselves before a request"""

    hx_ws: str | None = None
    """has been moved to an extension. Documentation for older versions"""

    def add_class(self, *classes: str) -> None:
        """Add classes to the 'class' attribute of the tag.

        Also makes the classes unique while preserving the order.

        (Convenience method.)
        """
        class_list = (self.class_ or "").split()
        # dict keeps insert order, but makes them unique
        class_dict = {cl: cl for cl in class_list}
        for cl in classes:
            assert cl.strip(), f"'{cl=}' cannot be empty."
            assert len(cl.split()) == 1, f"{cl=}only one class allowed"
            class_dict[cl] = cl

        self.class_ = " ".join(class_dict.keys())

    def remove_class(self, *classes: str) -> None:
        """Remove classes to the 'class' attribute of the tag.

        Also makes the classes unique while preserving the order.

        (Convenience method.)
        """
        class_list = (self.class_ or "").split()
        # dict keeps insert order, but makes them unique
        class_dict = {cl: cl for cl in class_list}
        for cl in classes:
            assert cl.strip(), f"'{cl=}' cannot be empty."
            assert len(cl.split()) == 1, f"{cl=}only one class allowed"
            class_dict.pop(cl, None)
        if class_dict:
            self.class_ = " ".join(class_dict.keys())
        else:
            self.class_ = None

    def _render_attr(self) -> str:
        result = super(HTMLElement, self)._render_attr()

        for name, value in self.data_attr.items():
            result += self._render_single_attr(f"data-{name}", value)

        for name, value in self.aria_attr.items():
            result += self._render_single_attr(f"aria-{name}", value)

        return result


_Method = Literal["post", "get", "dialog"]
_Target = str | Literal["_self", "_blank", "_parent", "_top"]
_CrossOrigin = Literal["anonymous", "use-credentials"]
_ReferrerPolicy = Literal[
    "no-referrer",
    "no-referrer-when-downgrade",
    "origin",
    "origin-when-cross-origin",
    "same-origin",
    "strict-origin",
    "strict-origin-when-cross-origin",
    "unsafe-url",
]


@dataclass(kw_only=True, slots=True, repr=False)
class a(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a"""

    download: bool | str = False
    href: str | None = None
    hreflang: str | None = None
    ping: str | None = None
    referrerpolicy: _ReferrerPolicy | None = None
    rel: str | None = None
    target: _Target | None = None
    type: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class abbr(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr"""


@dataclass(kw_only=True, slots=True, repr=False)
class acronym(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/acronym"""


@dataclass(kw_only=True, slots=True, repr=False)
class address(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address"""


@dataclass(kw_only=True, slots=True, repr=False)
class area(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area"""


@dataclass(kw_only=True, slots=True, repr=False)
class article(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article"""


@dataclass(kw_only=True, slots=True, repr=False)
class aside(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside"""


@dataclass(kw_only=True, slots=True, repr=False)
class audio(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio"""

    autoplay: bool = False
    controls: bool = False
    controlslist: Literal["nodownload", "nofullscreen", "noremoteplayback", None] = None
    crossorigin: _CrossOrigin | None = None
    disableremoteplayback: bool = False
    loop: bool = False
    muted: bool = False
    preload: Literal["none", "metadata", "auto", None] = None
    src: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class b(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b"""


@dataclass(kw_only=True, slots=True, repr=False)
class base(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base"""

    href: str | None = None
    target: _Target | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class bdi(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi"""


@dataclass(kw_only=True, slots=True, repr=False)
class bdo(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo"""

    dir_: Literal["ltr", "rtl", None] = None


@dataclass(kw_only=True, slots=True, repr=False)
class blockquote(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote"""

    cite: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class body(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body"""

    onafterprint: str | None = None
    onbeforeprint: str | None = None
    onbeforeunload: str | None = None
    onblur: str | None = None
    onerror: str | None = None
    onfocus: str | None = None
    onhashchange: str | None = None
    onlanguagechange: str | None = None
    onload: str | None = None
    onmessage: str | None = None
    onoffline: str | None = None
    ononline: str | None = None
    onpopstate: str | None = None
    onredo: str | None = None
    onresize: str | None = None
    onstorage: str | None = None
    onundo: str | None = None
    onunload: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class br(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br"""


@dataclass(kw_only=True, slots=True, repr=False)
class button(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button"""

    autofocus: bool = False
    disabled: bool = False
    form: str | None = None
    formaction: str | None = None
    formenctype: str | None = None
    formmethod: _Method | None = None
    formnovalidate: bool = False
    formtarget: _Target | None = None
    name: str | None = None
    popovertarget: bool = False
    popovertargetaction: Literal["hide", "show", "toggle", None] = None
    type: Literal["submit", "reset", "button", None] = None
    value: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class canvas(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas"""

    height: str | None = None
    width: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class caption(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption"""


@dataclass(kw_only=True, slots=True, repr=False)
class cite(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite"""


@dataclass(kw_only=True, slots=True, repr=False)
class code(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code"""


@dataclass(kw_only=True, slots=True, repr=False)
class col(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col"""

    span: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class colgroup(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup"""

    span: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class data(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data"""

    value: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class datalist(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist"""


@dataclass(kw_only=True, slots=True, repr=False)
class dd(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd"""


@dataclass(kw_only=True, slots=True, repr=False)
class del_(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del_"""

    cite: str | None = None
    datetime: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class details(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details"""

    open: bool = False


@dataclass(kw_only=True, slots=True, repr=False)
class dfn(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn"""


@dataclass(kw_only=True, slots=True, repr=False)
class dialog(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog"""

    open: bool = False


@dataclass(kw_only=True, slots=True, repr=False)
class div(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div"""


@dataclass(kw_only=True, slots=True, repr=False)
class dl(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl"""


@dataclass(kw_only=True, slots=True, repr=False)
class dt(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt"""


@dataclass(kw_only=True, slots=True, repr=False)
class em(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em"""


@dataclass(kw_only=True, slots=True, repr=False)
class embed(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed"""

    height: str | None = None
    src: str | None = None
    type: str | None = None
    width: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class fieldset(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset"""

    disabled: bool = False
    form: str | None = None
    name: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class figcaption(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption"""


@dataclass(kw_only=True, slots=True, repr=False)
class figure(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure"""


@dataclass(kw_only=True, slots=True, repr=False)
class footer(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer"""


@dataclass(kw_only=True, slots=True, repr=False)
class form(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form"""

    accept_charset: str | None = None
    autocapitalize: Literal["none", "sentences", "words", "characters", None] = None
    autocomplete: Literal["on", "off", None] = None
    name: str | None = None
    rel: str | None = None
    action: str | None = None
    enctype: str | None = None
    method: _Method | None = None
    novalidate: bool = False
    target: _Target | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class h1(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1"""


@dataclass(kw_only=True, slots=True, repr=False)
class h2(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2"""


@dataclass(kw_only=True, slots=True, repr=False)
class h3(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3"""


@dataclass(kw_only=True, slots=True, repr=False)
class h4(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4"""


@dataclass(kw_only=True, slots=True, repr=False)
class h5(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5"""


@dataclass(kw_only=True, slots=True, repr=False)
class h6(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6"""


@dataclass(kw_only=True, slots=True, repr=False)
class head(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head"""

    profile: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class header(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header"""


@dataclass(kw_only=True, slots=True, repr=False)
class hgroup(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup"""


@dataclass(kw_only=True, slots=True, repr=False)
class hr(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr"""


@dataclass(kw_only=True, slots=True, repr=False)
class html(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html"""

    xmlns: str | None = None

    def do_render(self, indent: str | None) -> str:
        if DOMConfig.FULL_XHTML:
            return (
                '<?xml version="1.0" encoding="UTF-8" ?>\n'
                '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" '
                '"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n'
            ) + super(html, self).do_render(indent)
        else:
            return "<!DOCTYPE html>\n" + super(html, self).do_render(indent)


@dataclass(kw_only=True, slots=True, repr=False)
class i(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i"""


@dataclass(kw_only=True, slots=True, repr=False)
class iframe(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe"""

    allow: str | None = None
    allowfullscreen: Literal["true", None] = None
    allowpaymentrequest: Literal["true", None] = None
    credentialless: Literal["true", None] = None
    csp: str | None = None
    height: str | None = None
    loading: Literal["eager", "lazy", None] = None
    name: str | None = None
    referrerpolicy: _ReferrerPolicy | None = None
    sandbox: str | None = None
    src: str | None = None
    srcdoc: str | None = None
    width: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class img(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img"""

    alt: str | None = None
    crossorigin: _CrossOrigin | None = None
    decoding: Literal["sync", "async", "auto", None] = None
    elementtiming: str | None = None
    fetchpriority: Literal["high", "low", "auto", None] = None
    height: str | None = None
    ismap: bool = False
    loading: Literal["eager", "lazy", None] = None
    referrerpolicy: _ReferrerPolicy | None = None
    sizes: str | None = None
    src: str | None = None
    srcset: str | None = None
    width: str | None = None
    usemap: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class input(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"""

    accept: str | None = None
    alt: str | None = None
    autocomplete: str | None = None
    autofocus: bool = False
    capture: str | None = None
    checked: bool = False
    dirname: str | None = None
    disabled: bool = False
    form: str | None = None
    formaction: str | None = None
    formenctype: Literal[
        "application/x-www-form-urlencoded", "multipart/form-data", "text/plain", None
    ] = None
    formmethod: _Method | None = None
    formnovalidate: bool = False
    formtarget: _Target | None = None
    height: str | None = None
    inputmode: Literal[
        "none", "text", "tel", "url", "email", "numeric", "decimal", "search", None
    ] = None
    list: str | None = None
    max: str | None = None
    maxlength: str | None = None
    min: str | None = None
    minlength: str | None = None
    multiple: bool = False
    name: str | None = None
    pattern: str | None = None
    placeholder: str | None = None
    popovertarget: str | None = None
    popovertargetaction: Literal["hide", "show", "toggle", None] = None
    readonly: bool = False
    required: bool = False
    size: str | None = None
    src: str | None = None
    step: str | None = None
    tabindex: str | None = None
    type: Literal[
        "button",
        "checkbox",
        "color",
        "date",
        "datetime-local",
        "email",
        "file",
        "hidden",
        "image",
        "month",
        "number",
        "password",
        "radio",
        "range",
        "reset",
        "search",
        "submit",
        "tel",
        "text",
        "time",
        "url",
        "week",
        None,
    ] = None
    value: str | None = None
    width: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class ins(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins"""

    cite: str | None = None
    datetime: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class kbd(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd"""


@dataclass(kw_only=True, slots=True, repr=False)
class label(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label"""

    for_: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class legend(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend"""


@dataclass(kw_only=True, slots=True, repr=False)
class li(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li"""

    value: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class link(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link"""

    as_: str | None = None
    crossorigin: _CrossOrigin | None = None
    disabled: bool = False
    fetchpriority: Literal["high", "low", "auto", None] = None
    href: str | None = None
    hreflang: str | None = None
    imagesizes: str | None = None
    imagesrcset: str | None = None
    integrity: str | None = None
    media: str | None = None
    prefetch: bool = False
    referrerpolicy: Literal[
        "no-referrer",
        "no-referrer-when-downgrade",
        "origin",
        "origin-when-cross-origin",
        "unsafe-url",
        None,
    ] = None
    rel: str | None = None
    sizes: str | None = None
    type: str | None = None
    blocking: bool = False


@dataclass(kw_only=True, slots=True, repr=False)
class main(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main"""


@dataclass(kw_only=True, slots=True, repr=False)
class map(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map"""

    name: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class mark(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark"""


@dataclass(kw_only=True, slots=True, repr=False)
class menu(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu"""


@dataclass(kw_only=True, slots=True, repr=False)
class meta(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta"""

    charset: str | None = None
    content: str | None = None
    http_equiv: str | None = None
    name: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class meter(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter"""

    value: str | None = None
    min: str | None = None
    max: str | None = None
    low: str | None = None
    high: str | None = None
    optimum: str | None = None
    form: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class nav(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav"""


@dataclass(kw_only=True, slots=True, repr=False)
class noscript(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript"""


@dataclass(kw_only=True, slots=True, repr=False)
class object(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object"""

    data: str | None = None
    form: str | None = None
    height: str | None = None
    name: str | None = None
    type: str | None = None
    usemap: str | None = None
    width: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class ol(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol"""

    reversed: bool = False
    start: str | None = None
    type: Literal["a", "A", "i", "I", "1"] | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class optgroup(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup"""

    disabled: bool = False
    label: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class option(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option"""

    disabled: bool = False
    label: str | None = None
    selected: bool = False
    value: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class output(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output"""

    for_: str | None = None
    form: str | None = None
    name: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class p(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p"""


@dataclass(kw_only=True, slots=True, repr=False)
class picture(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture"""


@dataclass(kw_only=True, slots=True, repr=False)
class portal(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/portal"""

    referrerpolicy: _ReferrerPolicy | None = None
    src: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class pre(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre"""


@dataclass(kw_only=True, slots=True, repr=False)
class progress(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress"""

    max: str | None = None
    value: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class q(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q"""

    cite: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class rp(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp"""


@dataclass(kw_only=True, slots=True, repr=False)
class rt(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt"""


@dataclass(kw_only=True, slots=True, repr=False)
class ruby(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby"""


@dataclass(kw_only=True, slots=True, repr=False)
class s(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s"""


@dataclass(kw_only=True, slots=True, repr=False)
class samp(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp"""


@dataclass(kw_only=True, slots=True, repr=False)
class script(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script"""

    async_: bool = False
    crossorigin: Literal["anonymous", "use-credentials"] | None = None
    defer: bool = False
    fetchpriority: Literal["high", "low", "auto", None] = None
    integrity: str | None = None
    nomodule: bool = False
    nonce: str | None = None
    referrerpolicy: _ReferrerPolicy | None = None
    src: str | None = None
    type: str | Literal["module", "importmap"] | None = None
    blocking: bool = False

    def do_render(self, indent: str | None) -> str:
        # script-tags must have a closing tag
        if self.children == []:
            self.children = [""]
        return super(script, self).do_render(indent)


@dataclass(kw_only=True, slots=True, repr=False)
class search(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/search"""


@dataclass(kw_only=True, slots=True, repr=False)
class section(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section"""


@dataclass(kw_only=True, slots=True, repr=False)
class select(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select"""

    autocomplete: str | None = None
    autofocus: bool = False
    disabled: bool = False
    form: str | None = None
    multiple: bool = False
    name: str | None = None
    required: bool = False
    size: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class slot(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot"""

    name: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class small(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small"""


@dataclass(kw_only=True, slots=True, repr=False)
class source(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source"""

    type: str | None = None
    src: str | None = None
    srcset: str | None = None
    sizes: str | None = None
    media: str | None = None
    height: str | None = None
    width: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class span(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span"""


@dataclass(kw_only=True, slots=True, repr=False)
class strong(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong"""


@dataclass(kw_only=True, slots=True, repr=False)
class style(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style"""

    media: str | None = None
    nonce: str | None = None
    title: str | None = None
    blocking: bool = False

    def do_render(self, indent: str | None) -> str:
        # style-tags must have a closing tag
        if self.children == []:
            self.children = [""]
        return super(style, self).do_render(indent)


@dataclass(kw_only=True, slots=True, repr=False)
class sub(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub"""


@dataclass(kw_only=True, slots=True, repr=False)
class summary(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary"""


@dataclass(kw_only=True, slots=True, repr=False)
class sup(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup"""


@dataclass(kw_only=True, slots=True, repr=False)
class table(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table"""


@dataclass(kw_only=True, slots=True, repr=False)
class tbody(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody"""


@dataclass(kw_only=True, slots=True, repr=False)
class td(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td"""

    colspan: str | None = None
    header: str | None = None
    rowspan: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class template(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template"""


@dataclass(kw_only=True, slots=True, repr=False)
class textarea(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea"""

    autocomplete: Literal["on", "off", None] = None
    autocorrect: Literal["on", "off", None] = None
    autofocus: bool = False
    cols: str | None = None
    dirname: str | None = None
    disabled: bool = False
    form: str | None = None
    maxlength: str | None = None
    minlength: str | None = None
    name: str | None = None
    placeholder: str | None = None
    readonly: bool = False
    required: bool = False
    rows: str | None = None
    wrap: Literal["hard", "soft", "off", None] = None


@dataclass(kw_only=True, slots=True, repr=False)
class tfoot(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot"""


@dataclass(kw_only=True, slots=True, repr=False)
class th(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th"""

    abbr: str | None = None
    colspan: str | None = None
    headers: str | None = None
    rowspan: str | None = None
    scope: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class thead(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead"""


@dataclass(kw_only=True, slots=True, repr=False)
class time(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time"""

    datetime: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class title(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title"""


@dataclass(kw_only=True, slots=True, repr=False)
class tr(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr"""


@dataclass(kw_only=True, slots=True, repr=False)
class track(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track"""

    default: bool = False
    kind: Literal[
        "subtitles", "captions", "descriptions", "chapters", "metadata", None
    ] = None
    label: str | None = None
    src: str | None = None
    srclang: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class u(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u"""


@dataclass(kw_only=True, slots=True, repr=False)
class ul(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul"""


@dataclass(kw_only=True, slots=True, repr=False)
class var(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var"""


@dataclass(kw_only=True, slots=True, repr=False)
class video(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video"""

    autoplay: bool = False
    controls: bool = False
    controlslist: Literal["nodownload", "nofullscreen", "noremoteplayback", None] = None
    crossorigin: _CrossOrigin | None = None
    disablepictureinpicture: bool = False
    disableremoteplayback: bool = False
    height: str | None = None
    loop: bool = False
    muted: bool = False
    playsinline: bool = False
    poster: str | None = None
    preload: Literal["none", "metadata", "auto", None] = None
    src: str | None = None
    width: str | None = None


@dataclass(kw_only=True, slots=True, repr=False)
class wbr(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr"""


@dataclass(kw_only=True, slots=True, repr=False)
class svg(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg"""


@dataclass(kw_only=True, slots=False, repr=False)
class path(HTMLElement):
    """see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path"""
